package com.xujie.sportsmeeting.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xujie.sportsmeeting.dto.RegistrationDTO;
import com.xujie.sportsmeeting.dto.RegistrationQueryDTO;
import com.xujie.sportsmeeting.entity.Athlete;
import com.xujie.sportsmeeting.entity.Registration;
import com.xujie.sportsmeeting.entity.SysUser;
import com.xujie.sportsmeeting.mapper.RegistrationMapper;
import com.xujie.sportsmeeting.service.AthleteService;
import com.xujie.sportsmeeting.service.RegistrationService;
import com.xujie.sportsmeeting.service.SysUserService;
import com.xujie.sportsmeeting.vo.RegistrationVO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 报名信息服务实现
 */
@Service
@RequiredArgsConstructor
public class RegistrationServiceImpl extends ServiceImpl<RegistrationMapper, Registration> implements RegistrationService {

    private final SysUserService sysUserService;
    private final AthleteService athleteService;

    @Override
    public IPage<RegistrationVO> getRegistrationPage(RegistrationQueryDTO queryDTO, Authentication authentication) {
        Page<RegistrationVO> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        
        LambdaQueryWrapper<Registration> wrapper = new LambdaQueryWrapper<>();
        
        // 根据用户角色过滤数据
        if (authentication != null) {
            String username = authentication.getName();
            SysUser currentUser = sysUserService.findByUsername(username);
            if (currentUser != null) {
                List<String> roles = sysUserService.findRolesByUserId(currentUser.getId());
                
                // 如果是运动员角色，只能查看自己的报名记录
                if (roles.contains("ATHLETE")) {
                    Athlete athlete = athleteService.findByUserId(currentUser.getId());
                    if (athlete != null) {
                        wrapper.eq(Registration::getAthleteId, athlete.getId());
                    } else {
                        // 如果找不到对应的运动员记录，返回空结果
                        return new Page<>(queryDTO.getCurrent(), queryDTO.getSize(), 0);
                    }
                }
            }
        }
        
        // 根据运动员ID查询
        if (queryDTO.getAthleteId() != null) {
            wrapper.eq(Registration::getAthleteId, queryDTO.getAthleteId());
        }
        
        // 根据项目ID查询
        if (queryDTO.getEventId() != null) {
            wrapper.eq(Registration::getEventId, queryDTO.getEventId());
        }
        
        // 根据审核状态查询
        if (queryDTO.getAuditStatus() != null) {
            wrapper.eq(Registration::getAuditStatus, queryDTO.getAuditStatus());
        }
        
        // 根据状态查询
        if (queryDTO.getStatus() != null) {
            wrapper.eq(Registration::getStatus, queryDTO.getStatus());
        }
        
        // 根据审核人查询
        if (queryDTO.getAuditUserId() != null) {
            wrapper.eq(Registration::getAuditUserId, queryDTO.getAuditUserId());
        }
        
        wrapper.orderByDesc(Registration::getCreateTime);
        
        return baseMapper.selectRegistrationPage(page, wrapper);
    }

    @Override
    @Transactional
    public boolean createRegistration(RegistrationDTO registrationDTO) {
        // 检查是否已报名
        if (isAlreadyRegistered(registrationDTO.getAthleteId(), registrationDTO.getEventId())) {
            throw new RuntimeException("该运动员已报名此项目");
        }
        
        Registration registration = new Registration();
        BeanUtils.copyProperties(registrationDTO, registration);
        registration.setAuditStatus(0); // 待审核
        registration.setStatus(1); // 正常
        registration.setRegistrationTime(LocalDateTime.now());
        
        return save(registration);
    }

    @Override
    @Transactional
    public boolean updateRegistration(Long id, RegistrationDTO registrationDTO) {
        Registration registration = getById(id);
        if (registration == null) {
            throw new RuntimeException("报名信息不存在");
        }
        
        // 只有待审核状态才能修改
        if (registration.getAuditStatus() != 0) {
            throw new RuntimeException("只有待审核状态的报名才能修改");
        }
        
        // 检查是否重复报名（排除当前记录）
        LambdaQueryWrapper<Registration> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Registration::getAthleteId, registrationDTO.getAthleteId())
               .eq(Registration::getEventId, registrationDTO.getEventId())
               .ne(Registration::getId, id);
        
        if (count(wrapper) > 0) {
            throw new RuntimeException("该运动员已报名此项目");
        }
        
        BeanUtils.copyProperties(registrationDTO, registration);
        registration.setId(id);
        
        return updateById(registration);
    }

    @Override
    @Transactional
    public boolean reviewRegistration(Long id, Integer status, String reviewRemark, Long reviewerId) {
        Registration registration = getById(id);
        if (registration == null) {
            throw new RuntimeException("报名信息不存在");
        }
        
        if (registration.getAuditStatus() != 0) {
            throw new RuntimeException("只有待审核状态的报名才能审核");
        }
        
        registration.setAuditStatus(status);
        registration.setAuditTime(LocalDateTime.now());
        registration.setAuditUserId(reviewerId);
        registration.setAuditRemark(reviewRemark);
        
        return updateById(registration);
    }

    @Override
    @Transactional
    public boolean cancelRegistration(Long id) {
        Registration registration = getById(id);
        if (registration == null) {
            throw new RuntimeException("报名信息不存在");
        }
        
        registration.setStatus(0); // 已取消
        return updateById(registration);
    }

    @Override
    @Transactional
    public boolean assignRaceNumber(Long id, String raceNumber) {
        Registration registration = getById(id);
        if (registration == null) {
            throw new RuntimeException("报名信息不存在");
        }
        
        if (registration.getAuditStatus() != 1) {
            throw new RuntimeException("只有审核通过的报名才能分配参赛号码");
        }
        
        // 检查参赛号码是否已存在
        if (isRaceNumberExists(registration.getEventId(), raceNumber)) {
            throw new RuntimeException("参赛号码已存在");
        }
        
        registration.setRaceNumber(raceNumber);
        return updateById(registration);
    }

    @Override
    public RegistrationVO getRegistrationDetail(Long id) {
        return baseMapper.selectRegistrationDetailById(id);
    }

    @Override
    public List<RegistrationVO> getRegistrationsByAthleteId(Long athleteId) {
        return baseMapper.selectByAthleteId(athleteId);
    }

    @Override
    public List<RegistrationVO> getApprovedRegistrationsByEventId(Long eventId) {
        return baseMapper.selectByEventId(eventId);
    }

    @Override
    public boolean isAlreadyRegistered(Long athleteId, Long eventId) {
        LambdaQueryWrapper<Registration> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Registration::getAthleteId, athleteId)
               .eq(Registration::getEventId, eventId)
               .in(Registration::getStatus, 0, 1); // 待审核或已通过
        
        return count(wrapper) > 0;
    }

    @Override
    public boolean isRaceNumberExists(Long eventId, String raceNumber) {
        if (!StringUtils.hasText(raceNumber)) {
            return false;
        }
        
        LambdaQueryWrapper<Registration> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Registration::getEventId, eventId)
               .eq(Registration::getRaceNumber, raceNumber);
        
        return count(wrapper) > 0;
    }
}
